/*
 * Copyright 2004 IBM Corporation.  ALL RIGHTS RESERVED.
 *
 * Author: PK
 * Date: 02/10/2004, Version: 1.0, File created.
 */
package com.ibm.crm.tma.adapter.messagelog;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//import java.sql.Date;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Properties;
import java.io.File;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
/**
 * The TMAMessageLog class will provide the API that will be used by all client
 * modules of the Adapter to write the Error, Warning, Informational, and Trace
 * messages to the log files. All Message Log API methods will be provided by
 * this class. Each application should get a reference to one instance of this
 * class at the beginning of the methos 'main' and continue using that same
 * object. All the classes in the same application should use the same message
 * log instance.
 */
public class TMAMessageLog {

    // Class variables.

    /**
     * Reference to the Singleton object which is the handle to Message Log Model. A
     * reference to this object can be obtained by calling the getMessageLogInstance()
     * class method. The first call to TMAMessageLog.getMessageLogInstance() will
     * construct the Singleton object, and set the object reference in this class
     * variable.
     */
    private static TMAMessageLog msgLogInstance = null;

    // Instance variables.

    private String appName = null;
    private String logDir = null;
    private String fileName = null;
    private int curHour = 0;
    private int newHour = 0;
    private FileOutputStream outputStream = null;
    static String userId = "";

    // Class methods.

    /**
     * Returns a reference to the Message Log model (TMAMessageLog) object.
     * All clients should invoke this class method to get a handle to the
     * TMAMessageLog object. This method will instantiate a model object if one
     * doesn't exists already. Since all the classes in the same application
     * should use the same message log instance, the application name passed
     * to this method should be same.
     */
    public static synchronized TMAMessageLog getMessageLogInstance(String theAppName) {

        if (msgLogInstance == null) {
            msgLogInstance = new TMAMessageLog(theAppName);
        }

        return msgLogInstance;
    }

    /**
     * Returns a reference to the Message Log model (TMAMessageLog) object.
     * All clients should invoke this class method to get a handle to the
     * TMAMessageLog object. This method will instantiate a model object if one
     * doesn't exists already. Since all the classes in the same application
     * should use the same message log instance, the application name passed
     * to this method should be same.
     */
    public static TMAMessageLog getMessageLogInstance() {

        return msgLogInstance;
    }

    // Constructors.

    /**
     * TMAMessageLog constructor. This method has been made private and supposed
     * to be called by the getMessageLogInstance() class method only.
     *
     * @param theappName : The name of the application. This will be used
     * to generate the name of the log file. The format of the file name will
     * be <application_name>.YYYYMonDD.log.
     *
     * @return an TMAMessageLog object reference.
     */
    public TMAMessageLog(String theAppName) {

        appName = theAppName;
        Calendar now = Calendar.getInstance();
        curHour = now.get(Calendar.HOUR_OF_DAY);
        Timestamp ts = new Timestamp(now.getTime().getTime());
        Timestamp TS = new Timestamp(new java.util.Date().getTime());
        String pgmDate = String.valueOf(TS);



            String fileprefix = pgmDate.substring(0,10);
            //System.out.println("ReportGenerationDate Property is: " + fileprefix);
            userId = System.getProperty("user.name");
            userId = userId.trim();
            String logFileBaseName = fileprefix + "-" + appName + "_" + userId + ".log";
//            System.out.println("logFileBaseName = " + logFileBaseName);




        // end of ADDED CODE
        //String logFileBaseName =
        //    ts.toString().substring(0, 10) + "-" + appName + ".log";
        String dirPath =
            TMADirectoryFinder.getDirectoryPath(TMAConstants.TMA_LOG_DIR);
        fileName = dirPath.concat("/" + logFileBaseName);
//        System.out.println("Message Log is logging to: " + logFileBaseName);
        openLogFile("\n\n\nMessage logging begins.");
    }

    private void openLogFile(String theString) {

        //System.out.println("Message log file name: " + fileName);

        try {
            outputStream = new FileOutputStream(fileName, true);
            Timestamp ts =
                new Timestamp(Calendar.getInstance().getTime().getTime());
            String hdr =
                theString
                    + "\nTime: "
                    + ts.toString()
                    + "\nApplication: "
                    + appName
                    + "\n";
            outputStream.write(hdr.getBytes());
        } catch (FileNotFoundException e) {
            System.out.println(
                "Message log file not found. No messages will be logged.");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Retuns the name of the file where the log messages are being logged by
     * the logger object.
     *
     * @return the name of the file.
     */
    private void prepareNewLogFile() {

        Calendar now = Calendar.getInstance();
        newHour = now.get(Calendar.HOUR_OF_DAY);
        DecimalFormat nf = new DecimalFormat("00");
        if (newHour < curHour) {
            try {
                curHour = newHour;
                String oldFileName = fileName;

                Timestamp ts = new Timestamp(now.getTime().getTime());
                String logFileBaseName =
                    ts.toString().substring(0, 10) + "-" + appName + ".log";
                String dirPath =
                    TMADirectoryFinder.getDirectoryPath(
                        TMAConstants.TMA_LOG_DIR);
                fileName = dirPath.concat("/" + logFileBaseName);

                String closingMsg =
                    "\n\nLogging to this file is closed. Please see log file: "
                        + fileName
                        + " for continuation.";
                outputStream.write(closingMsg.getBytes());
                outputStream.close();

                openLogFile(
                    "\n\n\nMessage logging continues from file: "
                        + oldFileName
                        + ".");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            // Moved up.
            /********************************************************************************
            curHour = newHour;
            Timestamp ts = new Timestamp(now.getTime().getTime());
            String logFileBaseName =
                ts.toString().substring(0, 10) + "-" + appName + ".log";
            String dirPath = TMADirectoryFinder.getDirectoryPath(TMAConstants.TMA_LOG_DIR);
            fileName = dirPath.concat("/" + logFileBaseName);
            openLogFile();
            ********************************************************************************/
        }
    }

    /**
     * Creates an entry in the log file when the program execution flow enters
     * a method. All client methods should invoke this API call as the first
     * excution statement in the method body. There should be only call to this
     * from a method.
     *
     * @param theClassName : the name of the class.
     * @param theMethodName : the name of the method being entered.
     */
    public void logEntry(String theClassName, String theMethodName) {

        // The team has decided not to have entry and exit traces.
        /****************************************************************
        prepareNewLogFile();
        String message =
            "Entering: "
                + getTimeStamp()
                + " "
                + theClassName
                + ":"
                + theMethodName;
        try {
            outputStream.write('\n');
            outputStream.write(message.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        *****************************************************************/
    }

    /**
     * Creates an entry in the log file when the program execution flow leaves
     * a method. All client methods should invoke this API call as the last
     * excution statement in the method body before all return or throw
     * statements. Hence many calls to this API will be required from a client
     * method.
     *
     * @param theClassName : the name of the class.
     * @param theMethodName : the name of the method being entered.
     */
    public void logExit(String theClassName, String theMethodName) {

        // The team has decided not to have entry and exit traces.
        /****************************************************************
        prepareNewLogFile();
        String message =
            "Exiting : "
                + getTimeStamp()
                + " "
                + theClassName
                + ":"
                + theMethodName;
        try {
            outputStream.write('\n');
            outputStream.write(message.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        ******************************************************************/
    }

    /**
     * Writes the error message into the module specific log file for the date.
     * All error messages from a midnight to next midnight (24 hours) will be
     * written to one file. This will prevent the log files from growing very
     * big.
     *
     * @param theMessageId : The message identification string. Format of the
     * message identification is 'TMAnnnE', 'TMAnnnW', 'TMAnnnI' where 'nnn'
     * is a three digit number from the range allocated to a module.
     * @param theClassName : Class name of the object that is reporting the
     * error.
     * @param theMethodName : Name of the method that is reporting this error.
     * @param theEerrorText : The error message.
     */
    public void logError(
        String theMessageId,
        String theClassName,
        String theMethodName,
        String theEerrorText) {

        prepareNewLogFile();
        String message =
            "Error   : "
                + getTimeStamp()
                + " "
                + theClassName
                + ":"
                + theMethodName
                + " "
                + theMessageId
                + ": "
                + theEerrorText;
        try {
            outputStream.write('\n');
            outputStream.write(message.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Writes the error message into the module specific log file for the date.
     * All error messages from a midnight to next midnight (24 hours) will be
     * written to one file. This will prevent the log files from growing very
     * big.
     *
     * @param theMessageId : The message identification string. Format of the
     * message identification is 'TMAnnnE', 'TMAnnnW', 'TMAnnnI' where 'nnn'
     * is a three digit number from the range allocated to a module.
     * @param theClassName : Class name of the object that is reporting the
     * error.
     * @param theMethodName : Name of the method that is reporting this error.
     * @param theEerrorText : The error message.
     * @param  theException : The exception to be logged along with the error
     * message.
     */
    public void logError(
        String theMessageId,
        String theClassName,
        String theMethodName,
        String theErrorText,
        Exception theException) {

        prepareNewLogFile();
        String message =
            "Error   : "
                + getTimeStamp()
                + " "
                + theClassName
                + ":"
                + theMethodName
                + " "
                + theMessageId
                + ": "
                + theErrorText;
        String exception = theException.getMessage();
        try {
            outputStream.write('\n');
            outputStream.write(message.getBytes());
            outputStream.write('\n');
            outputStream.write(exception.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Writes the warning message into the module specific log file for the date.
     * All log messages from a midnight to next midnight (24 hours) will be
     * written to one file. This will prevent the log files from growing very
     * big.
     *
     * @param theMessageId : The message identification string. Format of the
     * message identification is 'TMAnnnE', 'TMAnnnW', 'TMAnnnI' where 'nnn'
     * is a three digit number from the range allocated to a module.
     * @param theClassName : Class name of the object that is reporting the
     * warning.
     * @param theMethodName : Name of the method that is reporting this warning.
     * @param theWarningText : The warning message.
     */
    public void logWarning(
        String theMessageId,
        String theClassName,
        String theMethodName,
        String theWarningText) {

        prepareNewLogFile();
        String message =
            "Warning : "
                + getTimeStamp()
                + " "
                + theClassName
                + ":"
                + theMethodName
                + " "
                + theMessageId
                + ": "
                + theWarningText;
        try {
            outputStream.write('\n');
            outputStream.write(message.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Writes the warning message into the module specific log file for the date.
     * All log messages from a midnight to next midnight (24 hours) will be
     * written to one file. This will prevent the log files from growing very
     * big.
     *
     * @param theMessageId : The message identification string. Format of the
     * message identification is 'TMAnnnE', 'TMAnnnW', 'TMAnnnI' where 'nnn'
     * is a three digit number from the range allocated to a module.
     * @param theClassName : Class name of the object that is reporting the
     * warning.
     * @param theMethodName : Name of the method that is reporting this warning.
     * @param theWarningText : The warning message.
     * @param theException : The exception to be logged along with the warning
     * message.
     */
    public void logWarning(
        String theMessageId,
        String theClassName,
        String theMethodName,
        String theWarningText,
        Exception theException) {

        prepareNewLogFile();
        String message =
            "Warning : "
                + getTimeStamp()
                + " "
                + theClassName
                + ":"
                + theMethodName
                + " "
                + theMessageId
                + ": "
                + theWarningText;
        String exception = theException.getMessage();
        try {
            outputStream.write('\n');
            outputStream.write(message.getBytes());
            outputStream.write('\n');
            outputStream.write(exception.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Writes the informational message into the module specific log file for
     * the date. All log messages from after midnight to next midnight (24
     * hours) will be written to one file. This will prevent the log files from
     * growing very big.
     *
     * @param theMessageId : The message identification string. Format of the
     * message identification is 'TMAnnnE', 'TMAnnnW', 'TMAnnnI' where 'nnn'
     * is a three digit number from the range allocated to a module.
     * @param theClassName : Class name of the object that is reporting the
     * warning.
     * @param theMethodName : Name of the method that is reporting this warning.
     * @param theInfoText : The informational message.
     */
    public void logInformation(
        String theMessageId,
        String theClassName,
        String theMethodName,
        String theInfoText) {

        prepareNewLogFile();
        String message =
            "Info    : "
                + getTimeStamp()
                + " "
                + theClassName
                + ":"
                + theMethodName
                + " "
                + theMessageId
                + ": "
                + theInfoText;
        try {
            outputStream.write('\n');
            outputStream.write(message.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Writes the informational message into the module specific log file for
     * the date. All log messages from after midnight to next midnight (24
     * hours) will be written to one file. This will prevent the log files from
     * growing very big.
     *
     * @param theMessageId : The message identification string. Format of the
     * message identification is 'TMAnnnE', 'TMAnnnW', 'TMAnnnI' where 'nnn'
     * is a three digit number from the range allocated to a module.
     * @param theClassName : Class name of the object that is reporting the
     * warning.
     * @param theMethodName : Name of the method that is reporting this warning.
     * @param theInfoText : The informational message.
     * @param theException : The exception to be logged along with the
     * informational message.
     */
    public void logInformation(
        String theMessageId,
        String theClassName,
        String theMethodName,
        String theInfoText,
        Exception theException) {

        prepareNewLogFile();
        String message =
            "Info    : "
                + getTimeStamp()
                + " "
                + theClassName
                + ":"
                + theMethodName
                + " "
                + theMessageId
                + ": "
                + theInfoText;
        String exception = theException.getMessage();
        try {
            outputStream.write('\n');
            outputStream.write(message.getBytes());
            outputStream.write('\n');
            outputStream.write(exception.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    // Additions for CM-5280
    /**
     * Writes the data error message into the module specific log file for the date.
     * The data error messages are those specially formatted messages that are
     * destined to be consolidated later by another application and presented
     * to the data stewards.
     * All error messages from a midnight to next midnight (24 hours) will be
     * written to one file. This will prevent the log files from growing very
     * big.
     *
     * @param theMessageId : The message identification string. Format of the
     * message identification is 'TMAnnnE', 'TMAnnnW', 'TMAnnnI' where 'nnn'
     * is a three digit number from the range allocated to a module.
     * @param theClassName : Class name of the object that is reporting the
     * error.
     * @param theMethodName : Name of the method that is reporting this error.
     * @param theEerrorText : The specially formatted string for logging data errors.
     */
    public void logDataError(
        String theMessageId,
        String theClassName,
        String theMethodName,
        String theErrorText) {

        //check for lcia_only value - replace with env variable
        theErrorText = checkLciaGeo(theErrorText);

        prepareNewLogFile();
        String message =
            "Data    : "
                + getTimeStamp()
                + " "
                + theClassName
                + ":"
                + theMethodName
                + " "
                + theMessageId
                + ": "
                + theErrorText;


        try {
            outputStream.write('\n');
            outputStream.write(message.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Writes the error message into the module specific log file for the date.
     * The data error messages are those specially formatted messages that are
     * destined to be consolidated later by another application and presented
     * to the data stewards.
     * All error messages from a midnight to next midnight (24 hours) will be
     * written to one file. This will prevent the log files from growing very
     * big.
     *
     * @param theMessageId : The message identification string. Format of the
     * message identification is 'TMAnnnE', 'TMAnnnW', 'TMAnnnI' where 'nnn'
     * is a three digit number from the range allocated to a module.
     * @param theClassName : Class name of the object that is reporting the
     * error.
     * @param theMethodName : Name of the method that is reporting this error.
     * @param theEerrorText : The specially formatted string for logging data errors.
     * @param  theException : The exception to be logged along with the error
     * message.
     */
    public void logDataError(
        String theMessageId,
        String theClassName,
        String theMethodName,
        String theErrorText,
        Exception theException) {

        prepareNewLogFile();
        String message =
            "Data    : "
                + getTimeStamp()
                + " "
                + theClassName
                + ":"
                + theMethodName
                + " "
                + theMessageId
                + ": "
                + theErrorText;
        String exception = theException.getMessage();
        try {
            outputStream.write('\n');
            outputStream.write(message.getBytes());
            outputStream.write('\n');
            outputStream.write(exception.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Returns a formatted string with delimiters as required by the
     * specification of the data error logging format for TMA.
     * @param PgmName   The name of the class issuing the data error.
     * @param Text      Text of the error being reported.
     * @param Geo       Geography. NA, EMEA or AP.
     * @param Sev       Severity - 1=fatal, 2=rejected, 3-warning, 4-system
     * @param LOV_TYPE  Value of the LOV_TYPE
     * @param LOV_VAL   Value of the LOV_VAL
     * @param LOV_NAME  Value of the LOV_NAME
     * @param LOV_SUB_TYPE  Value of the LOV_SUB_TYPE
     * @param LOV_LANG_ID   Value of the LOV_LANG_ID
     *
     * @return Returns the formatted string
     */

    public String BuildLogString(
        String PgmName,
        String Text,
        String Geo,
        String Sev,
        String LOV_SUB_TYPE,
        String LOV_TYPE,
        String LOV_VAL,
        String LOV_NAME,
        String LOV_LANG_ID,
        String SiebelOnly)

    {
        String Del = " ^";
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHmmss");
        String Date = formatter.format(new Date());
        String LogString = Date + Del
            + PgmName + Del
            + Text + Del
            + Geo + Del
            + Sev + Del
            + LOV_LANG_ID + Del
            + LOV_TYPE + Del
            + LOV_VAL + Del
            + LOV_NAME + Del
            + LOV_SUB_TYPE + Del
            + SiebelOnly;
        return LogString;
    }

//     End of Additions for CM-5280


    private String getTimeStamp() {

        Timestamp ts =
            new Timestamp(Calendar.getInstance().getTime().getTime());
        return ts.toString();
    }
    /**
     * @return
     */
    public static TMAMessageLog getMsgLogInstance() {

        return msgLogInstance;
    }

    /**
     * @return
     */
    public String getAppName() {

        return appName;
    }

    /**
     * @return
     */
    public int getCurHour() {

        return curHour;
    }

    /**
     * @return
     */
    public int getNewHour() {

        return newHour;
    }

    /**
     * @return
     */
    public FileOutputStream getOutputStream() {

        return outputStream;
    }

    /**
     * Returns the full path to the directory where the module log files will
     * be written.
     *
     * @return the path to the logging directory.
     */
    private String getLogDir() {

        return logDir;
    }

    /**
     * Sets the name of the file where the log messages will be written by the
     * logger object.
     *
     * @param theFileName : the name of the log file.
     */
    private void setFileName(String theFileName) {

        fileName = theFileName;
    }

    /**
     * Sets the full path to the directory where the module log files will be
     * written.
     *
     * @param theLogDir : the path to the logging directory.
     */
    private void setLogDir(String theLogDir) {

        logDir = theLogDir;
    }
    public String checkLciaGeo (String input)
        {
             String output = "";
             String [] pArray;
             pArray = input.split("\\^");
             int x = pArray.length;
             if (pArray[3].trim().compareToIgnoreCase("lcia_only") == 0)
             {
                 pArray[3] = System.getProperty("LCIA_CURRENT_ENV");
             }
             for (int i=0;i < x;i++)
             {
                if (i > 0)
                {
                    output = output + "^";
                }
                output = output + pArray[i];
             }
             return output;
    }
}
